#include <iostream>
#include <string>
#include <cstring>
#include <cerrno>
#include <sys/unistd.h>
#include <wait.h>
#include <unistd.h>

const int size = 1024;

std::string GetOtherMessage()
{
    static int cnt = 0;
    // stoi : string -> int
    // to_string : int -> string
    std::string messagecnt = std::to_string(cnt);
    cnt++;
    pid_t self_id = getpid();
    std::string messagepid = std::to_string(self_id);

    std::string message = "messagecnt: ";
    message += messagecnt;
    message += ", my pid is : ";
    message += messagepid;

    return message;
}

void SubProcessWrite(int wfd)
{
    int pipesize = 0;
    std::string message = "father, I am your son prcess!";
    char c ='A';
    while(true)
    {
        std::cerr << "+++++++++++++++++++++++++++++++++" << std::endl;
        // 子进程发给父进程的消息
        std::string info = message + GetOtherMessage();
        // 写入管道的时候，没有写入\0, 读取时加 \0
        write(wfd, info.c_str(), info.size());

        std::cerr << info << std::endl;

        // 子进程写慢点
        // sleep(1);

        // write(wfd, &c, 1);
        // std::cout << "pipesize: " << ++pipesize
        //     << ", write charator is : " << c++ << std::endl;
        // if(c == 'G')    break;

        // sleep(1);
    }

    std::cout << "child quit ..." << std::endl;
}

void FatherProcessRead(int rfd)
{
    char inbuffer[size]; // c99 , gnu g99
    while (true)
    {
        sleep(2);
        std::cout << "-----------------------------------" << std::endl;
        // sleep(500);
        // sizeof(inbuffer)->strlen(inbuffer);
        ssize_t n = read(rfd, inbuffer, sizeof(inbuffer) - 1);
        if (n > 0)
        {
            inbuffer[n] = 0; // == '\0'
            std::cout  << inbuffer << std::endl;
        }
        else if (n == 0)
        {
            // 如果read的返回值是0，表示写端直接关闭了，我们读到了文件的结尾
            std::cout << "client quit, father get return val: "
                << n << " father quit too!" << std::endl;
            break;
        }
        else if(n < 0)
        {
            std::cerr << "read error" << std::endl;
            break;
        }

        // sleep(1);
        // break;
    }
}
    
int main()
{
    // 1.创建管道
    int pipefd[2];
    int n = pipe(pipefd);   // 输出型参数，rfd，wfd
    if(n != 0)
    {
        std::cout << "errno: " << errno << ": " 
            << "errstring: " << strerror(errno) << std::endl;
        return 1;
    }
    // pipefd[0] -> 0 -> 嘴 - 读  pipefd[1] -> 1 -> 笔 - 写
    std::cout << "pipefd[0]: " << pipefd[0] 
        << ", pipefd[1]: " << pipefd[1] << std::endl;
    sleep(1);

    // 2.创建子进程
    pid_t id = fork();
    if(id == 0)
    {
        std::cout << "子进程关闭不需要的fd了, 准备发消息了" << std::endl;
        sleep(1);
        // 子进程 -- write
        // 3.关闭不需要的fd
        close(pipefd[0]);
        // if(fork() > 0)  exit(0);
        SubProcessWrite(pipefd[1]);

        close(pipefd[1]);
        exit(0);
    }

    std::cout << "父进程关闭不需要的fd了, 准备收消息了" << std::endl;
    sleep(1);
    
    // 父进程 -- read
    // 3.关闭不需要的fd
    close(pipefd[1]);
    FatherProcessRead(pipefd[0]);
    std::cout << "5s, father close rfd" << std::endl;
    sleep(5);
    close(pipefd[0]);

    int status = 0;
    pid_t rid = waitpid(id, &status, 0);
    if (rid > 0)
    {
        std::cout << "wait child process done, exit sig: "
            << (status&0x7f) << std::endl;
        std::cout << "wait child process done, exit code(ign): "
            << ((status>>8)&0xFF) << std::endl;
    }

    return 0;
}